﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Mail;
using System.Net.Configuration;
using System.Configuration;

namespace SpamMail.Source.App.Classes {
    class EmailUtiltiies {
        /// <summary>
        /// delegate method that will be used to switch between Sync and
        /// Async call for the send mail.
        /// </summary>
        /// <param name="smtpClient">Mail client</param>
        /// <param name="message">Message to be sent</param>
        private delegate void SendMailMethod(SmtpClient smtpClient, MailMessage message);


        /// <summary>
        /// This method sends an email synchronously
        /// </summary>
        /// <param name="from">From address</param>
        /// <param name="to">Receiver's Address</param>
        /// <param name="subject">Email subject</param>
        /// <param name="messageBody">Email body</param>
        public static void SendSync(string from, string to, string subject, string messageBody) {
            try {
                Send(from, new string[] { to }, subject, messageBody, true,
                    delegate(SmtpClient smtpClient, MailMessage message) {
                        smtpClient.Send(message);
                    }, null);
            } catch (EmailUtilitiiesException) {
                throw;
            }
        }
        /// <summary>
        /// This method sends an email synchronously
        /// </summary>
        /// <param name="from">From address</param>
        /// <param name="to">Receiver's Address</param>
        /// <param name="subject">Email subject</param>
        /// <param name="messageBody">Email body</param>
        /// <param name="attachments">The attchments to be sent with the email</param>
        public static void SendSync(string from, string to, string subject, string messageBody, params Attachment[] attachments) {
            try {
                Send(from, new string[] { to }, subject, messageBody, true, delegate(SmtpClient smtpClient, MailMessage message) {
                    smtpClient.Send(message);
                }, attachments);
            } catch (EmailUtilitiiesException) {
                throw;
            }
        }

        /// <summary>
        /// This method sends an email synchronously
        /// </summary>
        /// <param name="from">From address</param>
        /// <param name="to">Receiver's Address</param>
        /// <param name="subject">Email subject</param>
        /// <param name="messageBody">Email body</param>
        /// <param name="isBodyHtml">Indicate the body message is to support HTML</param>
        public static void SendSync(string from, string to, string subject, string messageBody, bool isBodyHtml) {
            try {
                Send(from, new string[] { to }, subject, messageBody, isBodyHtml, delegate(SmtpClient smtpClient, MailMessage message) {
                    smtpClient.Send(message);
                }, null);
            } catch (EmailUtilitiiesException) {
                throw;
            }
        }
        /// <summary>
        /// This method sends an email synchronously
        /// </summary>
        /// <param name="from">From address</param>
        /// <param name="to">Receiver's Address</param>
        /// <param name="subject">Email subject</param>
        /// <param name="messageBody">Email body</param>
        /// <param name="isBodyHtml">Indicate the body message is to support HTML</param>
        /// <param name="attachments">The attchments to be sent with the email</param>
        public static void SendSync(string from, string to, string subject, string messageBody, bool isBodyHtml, params Attachment[] attachments) {
            try {
                Send(from, new string[] { to }, subject, messageBody, isBodyHtml, delegate(SmtpClient smtpClient, MailMessage message) {
                    smtpClient.Send(message);
                }, attachments);
            } catch (EmailUtilitiiesException) {
                throw;
            }
        }
        /// <summary>
        /// This method sends an email synchronously
        /// </summary>
        /// <param name="from">From address</param>
        /// <param name="to">Recievers' Addresses</param>
        /// <param name="subject">Email subject</param>
        /// <param name="messageBody">Email body</param>
        public static void SendSync(string from, string[] to, string subject, string messageBody) {
            try {
                Send(from, to, subject, messageBody, true, delegate(SmtpClient smtpClient, MailMessage message) {
                    smtpClient.Send(message);
                }, null);
            } catch (EmailUtilitiiesException) {
                throw;
            }
        }


        /// <summary>
        /// This method sends an email synchronously
        /// </summary>
        /// <param name="from">From address</param>
        /// <param name="to">Receivers' Addresses</param>
        /// <param name="subject">Email subject</param>
        /// <param name="messageBody">Email body</param>
        /// <param name="attachments">The attchments to be sent with the email</param>
        public static void SendSync(string from, string[] to, string subject, string messageBody, params Attachment[] attachments) {
            try {
                Send(from, to, subject, messageBody, true,
                    delegate(SmtpClient smtpClient, MailMessage message) {
                        smtpClient.Send(message);
                    }, attachments);
            } catch (EmailUtilitiiesException) {
                throw;
            }
        }


        /// <summary>
        /// This method sends an email asynchronously
        /// </summary>
        /// <param name="from">From address</param>
        /// <param name="to">Receiver's Address</param>
        /// <param name="subject">Email subject</param>
        /// <param name="messageBody">Email body</param>
        public static void SendAsync(string from, string to, string subject, string messageBody) {
            try {
                // This is an asyncronouse call that will block the thread call
                // we put the current date time as a unique identifier for user token
                // this call, at this stage we are not intersted in this token
                // you can refer to http://msdn2.microsoft.com/en-us/library/x5x13z6h.aspx
                Send(from, new string[] { to }, subject, messageBody, true,
                    delegate(SmtpClient smtpClient, MailMessage message) {
                        smtpClient.SendAsync(message, DateTime.Now.ToString());
                    }, null);
            } catch (EmailUtilitiiesException) {
                throw;
            }
        }


        /// <summary>
        /// This method sends an email asynchronously
        /// </summary>
        /// <param name="from">From address</param>
        /// <param name="to">Receiver's Address</param>
        /// <param name="subject">Email subject</param>
        /// <param name="messageBody">Email body</param>
        /// <param name="attachments">The attchments to be sent with the email</param>
        public static void SendAsync(string from, string to, string subject, string messageBody, params Attachment[] attachments) {
            try {
                // This is an asyncronouse call that will block the thread call
                // we put the current date time as a unique identifier for user token
                // this call, at this stage we are not intersted in this token
                // you can refer to http://msdn2.microsoft.com/en-us/library/x5x13z6h.aspx
                Send(from, new string[] { to }, subject, messageBody, true,
                    delegate(SmtpClient smtpClient, MailMessage message) {
                        smtpClient.SendAsync(message, DateTime.Now.ToString());
                    }, attachments);
            } catch (EmailUtilitiiesException) {
                throw;
            }
        }

        /// <summary>
        /// This is the main method that will send the email message
        /// </summary>
        /// <param name="from">From address</param>
        /// <param name="to">Receivers' Addresses</param>
        /// <param name="subject">Email subject</param>
        /// <param name="messageBody">Email body</param>
        /// <param name="isBodyHtml">Indicate the body message is to support HTML</param>
        /// <param name="sendDelegate">Delegate method that define the sending type (Sync/Async)</param>
        /// <param name="attachments">The attchments to be sent with the email</param>
        private static void Send(string from, string[] to, string subject, string messageBody, bool isBodyHtml, SendMailMethod sendDelegate,
            params Attachment[] attachments) {
            SmtpClient emailClient;
            try {
                emailClient = new SmtpClient();
                // Prepare the MailMessage contents
                MailMessage message = new MailMessage();
                message.Subject = subject;
                message.Body = messageBody;
                message.Sender = new MailAddress(from);
                // Set the receivers' addresses

                foreach (string address in to)
                    message.To.Add(new MailAddress(address));

                SmtpSection smtpSec = (SmtpSection)ConfigurationManager.GetSection("system.net/mailSettings/smtp");

                // Set the SMTP host.     
                emailClient = new SmtpClient(smtpSec.Network.Host);
                // if the email credentials are enabled then get them from the
                // config file.
                if (App.Default.EmailCredentialsEnabled) {
                    System.Net.NetworkCredential SMTPUserInfo = new System.Net.NetworkCredential(smtpSec.Network.UserName, smtpSec.Network.Password);
                    emailClient.UseDefaultCredentials = true;
                    emailClient.EnableSsl = true;
                    emailClient.Credentials = SMTPUserInfo;
                }

                // set to indicate whethere the email support HTML or not
                message.IsBodyHtml = isBodyHtml;
                // set the encoding for the message body
                message.BodyEncoding = System.Text.Encoding.UTF8;
                message.SubjectEncoding = System.Text.Encoding.UTF8;
                // Add the attachments if they are present.
                if (attachments != null) {
                    // Add the attachments
                    foreach (Attachment attchment in attachments)
                        message.Attachments.Add(attchment);
                }
                // Call the send delegate method
                sendDelegate(emailClient, message);

            } catch (Exception ex) {
                throw new EmailUtilitiiesException("Không thể gửi mail", ex);
            }
        }
    }
}
